package com.khaled.protclass.model.loader;

import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;

import com.khaled.protclass.model.base.IProtein;
import com.khaled.protclass.model.bean.protein.SequenceProtein;
import com.khaled.protclass.model.util.Constants;
import com.khaled.protclass.model.util.UtilDirectory;

public class SequenceProteinLoader extends ProteinLoader
{
	public ArrayList<IProtein> loadProteins(String path, String protein_class) throws IOException
	{
		ArrayList<IProtein> proteinList = new ArrayList<IProtein>();

		if (UtilDirectory.isFile(path))
		{
			proteinList.addAll(readProteinsFromFile(path, protein_class));
		}
		else
		{
			for (String fileName : UtilDirectory.getDirectoryChildren(path, Constants.FASTA_EXE))
			{
				proteinList.addAll(readProteinsFromFile(path + "\\" + fileName, protein_class));
			}
		}
		return proteinList;
	}
	
	private ArrayList<IProtein> readProteinsFromFile(String path, String protein_class) throws IOException
	{
		ArrayList<String> fileLines = UtilDirectory.readFileLines(path);	
		return readProteins(fileLines, protein_class);
	}
	
	private ArrayList<IProtein> readProteins(ArrayList<String> fileLines, String protein_class)
	{
		ArrayList<IProtein> proteinList = new ArrayList<IProtein>();
		String proteinId = null;
		String proteinSequence = "";

		for (String line : fileLines)
		{
			String strLine = line.trim();

			if ("".equals(strLine))
			{
				if (proteinId != null)
				{
					addProtein(proteinList, new SequenceProtein(proteinId, proteinSequence, protein_class));

					proteinSequence = "";
					proteinId = null;
				}
			}
			else if (strLine.startsWith(">"))
			{
				if (proteinId != null)
				{
					addProtein(proteinList, new SequenceProtein(proteinId, proteinSequence, protein_class));

				}
				proteinId = strLine.trim();
				/*
				 * sometimes proteinId contains more information rather than its
				 * id so naming the protein with all of these information may
				 * cause some problems specially while saving it in a file (the
				 * file name will be too long)
				 * 
				 * so I assume that protein information is splited by | sign and
				 * the protein id is located in the second item
				 * 
				 * ex: >gi|10173129|dbj|BAB04235.1| surface adhesin A precursor
				 * [Bacillus halodurans] the protein Id is 10173129
				 * 
				 * TODO: consider other representations
				 */

				StringTokenizer proSplits = new StringTokenizer(proteinId, "|");
				if (proSplits.countTokens() > 1)
				{
					proSplits.nextToken();

					proteinId = ">" + proSplits.nextToken();
				}
				// /////////////////////////////////////////////////////////////////

				proteinSequence = "";
			}
			else
			{
				proteinSequence += strLine;
			}
		}
		if (proteinId != null)
		{
			addProtein(proteinList, new SequenceProtein(proteinId, proteinSequence, protein_class));
		}
		
		return proteinList;
	}
	
	private void addProtein(ArrayList<IProtein> proteinList, IProtein newProtein)
	{
		while(proteinList.contains(newProtein))
		{
			newProtein.setProteinID(newProtein.getProteinID()+"+");
		}
		proteinList.add(newProtein);
		
	}

	@Override
	public ArrayList<IProtein> loadProteinsFromString(String proteinSequence, String proteinClass)
	{
		String[] fastaLines = proteinSequence.split("\n");
		ArrayList<String> lines = new ArrayList<String>();
		for(String l : fastaLines)
		{
			lines.add(l);
		}
		
		return readProteins(lines, proteinClass);
	}
}
